package com.iwhalecloud.citybrain.flow.platform.manager.infrastructure.repository;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.iwhalecloud.citybrain.flow.platform.manager.application.common.enums.*;
import com.iwhalecloud.citybrain.flow.platform.manager.application.common.threadlocal.SdkCallTag;
import com.iwhalecloud.citybrain.flow.platform.manager.application.service.ProcessInstanceMonitorService;
import com.iwhalecloud.citybrain.flow.platform.manager.application.service.ResolveCandidateService;
import com.iwhalecloud.citybrain.flow.platform.manager.application.service.UserService;
import com.iwhalecloud.citybrain.flow.platform.manager.application.utils.FlowUtils;
import com.iwhalecloud.citybrain.flow.platform.manager.application.utils.ModelUtils;
import com.iwhalecloud.citybrain.flow.platform.manager.application.utils.SessionUtils;
import com.iwhalecloud.citybrain.flow.platform.manager.application.utils.SpringUtils;
import com.iwhalecloud.citybrain.flow.platform.manager.common.ResponseResult;
import com.iwhalecloud.citybrain.flow.platform.manager.common.client.FlowNodeRecordsDTO;
import com.iwhalecloud.citybrain.flow.platform.manager.common.client.HttpFlowRecordsQueryDto;
import com.iwhalecloud.citybrain.flow.platform.manager.common.client.HttpGetTaskDto;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.enums.ApproveStatus;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.enums.CommentTypeEnum;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.enums.NoticeTypeEnum;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.*;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.form.TaskFormDetailVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.log.FlowCommonOperateLogVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.monitor.*;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.notice.FlowRuTaskNoticeChannelVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.userentity.CandidateEntity;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.userentity.UserInfo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.repository.*;
import com.iwhalecloud.citybrain.flow.platform.manager.infrastructure.entities.*;
import com.iwhalecloud.citybrain.flow.platform.manager.infrastructure.mapper.FlowTaskInstApproverDAO;
import com.iwhalecloud.citybrain.flow.platform.manager.infrastructure.mapper.FlowVariableDAO;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.flowable.bpmn.model.Process;
import org.flowable.bpmn.model.*;
import org.flowable.engine.*;
import org.flowable.engine.common.impl.interceptor.Command;
import org.flowable.engine.common.impl.interceptor.CommandContext;
import org.flowable.engine.impl.persistence.entity.ByteArrayEntityManagerImpl;
import org.flowable.engine.impl.util.ProcessDefinitionUtil;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.task.Comment;
import org.flowable.identitylink.api.IdentityLink;
import org.flowable.task.api.Task;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.flowable.variable.api.history.HistoricVariableInstance;
import org.flowable.variable.api.history.HistoricVariableInstanceQuery;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author lilh
 * @date 2019-07-29 14:57
 */
@Service
public class FlowMonitorRepositoryImpl implements FlowMonitorRepository {

    private Logger logger = LoggerFactory.getLogger(this.getClass());


    private static Map<String, String> auditCodeToDescMap = new HashMap<String, String>() {

        private static final long serialVersionUID = -3735877190358288393L;

        {
            put("pass", "通过");
            put("unpass", "不通过");
        }
    };
    private static final String START_NODE_TYPE = "start";
    @Autowired
    private ProcessInstanceMonitorService processInstanceMonitorService;

    @Autowired
    private FlowTaskTraceRepository taskTraceService;

    @Autowired
    private FlowProcessInstanceTraceRepository processInstanceTraceService;

    @Autowired
    private HistoryService historyService;

    @Autowired
    private TaskService taskService;

    @Autowired
    private FlowRuTimeoutSettingRepository flowRuTimeoutSettingRepository;

    @Autowired
    private FlowRuTaskNoticeChannelRepository flowRuTaskNoticeChannelRepository;

    @Autowired
    private FlowParticipantRepository flowParticipantRepository;

    @Autowired
    private FlowCommonOperateLogRepository flowCommonOperateLogRepository;

    @Autowired
    private FlowMultiInstanceTaskTraceRepository flowMultiInstanceTaskTraceRepository;

    @Autowired
    private FlowRuleActionAuditLogRepository flowRuleActionAuditLogRepository;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private FlowProcessInstanceTraceRepository flowProcessInstanceTraceRepository;


    @Autowired
    private FlowFormRepository formRepository;

    @Autowired
    private FlowActivityAproverRepository  flowActivityAproverRepository;

    @Autowired
    private   FlowTaskInstApproverRepository  flowTaskInstApproverRepository;

    @Autowired
    private ManagementService managementService;

    @Autowired
    private FlowTaskTraceRepository flowTaskTraceRepository;

    @Autowired
    private ResolveCandidateService resolveCandidateService;

    @Autowired
    private FlowTaskService flowTaskService;

    @Autowired
    FlowTitleExpressionResultRepository flowTitleExpressionResultRepository;

    @Autowired
    private UserService userService;

    @Autowired
    private FlowVariableDAO flowVariableDAO;

    @Autowired
    private FlowTaskInstApproverDAO flowTaskInstApproverDAO;

    @Autowired
    private FlowProcessInstanceOperateTraceRepository flowProcessInstanceOperateTraceRepository;

    @Override
    public ResponseResult doAction(ProcessInstanceActionVo processInstanceActionVo) {
        return processInstanceMonitorService.doAction(processInstanceActionVo);
    }

    @Override
    public List<FlowRecordVo> listFlowRecords(String processInstanceId) {
        List<FlowRecordVo> result = new LinkedList<>();
        //发起节点
        resolveStartNode(processInstanceId, result);
        if (result.size() < 1) {
            return result;
        }
        FlowProcessInstanceTraceVo processInstanceTrace = flowProcessInstanceTraceRepository.getProcessInstanceTraceByProcessInstanceId(processInstanceId);
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processInstanceTrace.getProcessDefinitionId()).singleResult();
        //获取流程资源
        InputStream inputStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), processDefinition.getResourceName() + ".json");
        ProcessModelVo processModel = ModelUtils.getInstance().streamToModel(inputStream);
        /*if(ProcessInstanceStatusEnum.END.getCode().equals(processInstanceTrace.getLinkStatus())){
            return  new ArrayList<>();
        }*/
        //获取各个节点的权限
        Map<String, Object> nodeAuth = ModelUtils.getInstance().userTaskNodeAuth(processModel);

        List<FlowTaskTraceVo> taskTraces = taskTraceService.listByProcessInstanceId(processInstanceId);
        this.processFlowRecordList(taskTraces);

        //处理历史任务和当前运行的任务
        convertHistoricTaskAndRunningTaskToResult(taskTraces, result, nodeAuth);

        //记录审批意见
        List<Comment> comments = taskService.getProcessInstanceComments(processInstanceId);
        resolveFlowRecordComment(result,comments);

        for(FlowRecordVo recordVo : result){
            String taskId = recordVo.getTaskId();
            if(StringUtils.isNotEmpty(taskId)){
                String approvalStatus =  this.getApprovalStatus(taskId);
                recordVo.setApprovalStatus(approvalStatus);
            }
            List<FlowRecordVo> children = recordVo.getChildren();
            if(children !=null ){
                for(FlowRecordVo flowRecordVo : children){
                    if(TaskLinkStatusEnum.TRANSFER.getCode().equals(flowRecordVo.getApprovalStatus())){
                        continue;
                    }
                    String approvalStatus =  this.getApprovalStatus(flowRecordVo.getTaskId());
                    flowRecordVo.setApprovalStatus(approvalStatus);
//                    流程详情-流程记录中待处理任务未显示（已读、未读）状态，耗时较多，先取消
//                    FlowTaskInstApprover approver =  flowTaskInstApproverDAO.selectByByTaskIdAndUserId(flowRecordVo.getTaskId(),flowRecordVo.getOperatorCode());
//                    flowRecordVo.setReadFlag(null!=approver && null!=approver.getReadFlag()?approver.getReadFlag():0);

                }
            }

            //自定义标题
            if(StringUtils.isNotEmpty(recordVo.getActivityId())){
                recordVo.setCustomTitle(flowTitleExpressionResultRepository.getTitleExpressionResultByProcessInstanceIdAndActivityId(recordVo.getProcessInstanceId(),recordVo.getActivityId()));
            }
        }

        //增加局部变量返回
        reVarFromResult(result);

        return result;
    }

    @Override
    public List<HttpFlowRecordsQueryVo> batchQueryFlowRecords(HttpFlowRecordsQueryDto httpFlowRecordsQueryDto){
        return flowTaskTraceRepository.batchQueryFlowRecords(httpFlowRecordsQueryDto);
    }

    /**
     * 根据配置的流程模型编码获取任务节点列表
     *
     * @return
     */
    @Override
    public List<FlowNodeRecordsDTO> getTaskCodeList(HttpGetTaskDto httpGetTaskDto) {

        // 根据流程模型编码查询在途的任务列表
        List<HttpFlowNodeRecordsQueryVo> taskInstances = flowTaskTraceRepository.getTaskCodeList(httpGetTaskDto);
        if(CollectionUtils.isEmpty(taskInstances)) {
            return Collections.emptyList();
        }

        // 按照流程实例ID进行分组
        Map<String, List<HttpFlowNodeRecordsQueryVo>> dataMap = new HashMap<>();
        for (HttpFlowNodeRecordsQueryVo queryVo : taskInstances) {
            // 首先根据key取出是否存在对应的value,如果不存在,则新创建一个集合添加进去,否则直接add进去
            List<HttpFlowNodeRecordsQueryVo> dataList = dataMap.get(queryVo.getProcessInstanceId());
            if(CollectionUtils.isEmpty(dataList)) {
                List<HttpFlowNodeRecordsQueryVo> initDataList = new ArrayList<>();
                initDataList.add(queryVo);
                // 流程实例ID最为key
                dataMap.put(queryVo.getProcessInstanceId(), initDataList);
            } else {
                dataList.add(queryVo);
                dataMap.put(queryVo.getProcessInstanceId(), dataList);
            }
        }

        // 按照流程实例ID分组完成之后,再迭代map,并取出每个map的key对应的value进行检查
        if(MapUtils.isEmpty(dataMap)) {
            return Collections.emptyList();
        }

        // 存储状态条件过滤之后的数据集合
        List<FlowNodeRecordsDTO> filterQueryDtoList = new ArrayList<>();

        // Map集合循环遍历
        for (Map.Entry<String, List<HttpFlowNodeRecordsQueryVo>> mapObj : dataMap.entrySet()) {
            // 取出对应的value
            List<HttpFlowNodeRecordsQueryVo> mapDataList = mapObj.getValue();
            if(CollectionUtils.isNotEmpty(mapDataList)) {
                int ctn = 0;
                // 一个key只对应一个对象
                FlowNodeRecordsDTO flowNodeRecordsDTO = new FlowNodeRecordsDTO();
                // 检验每个任务是否做了驳回操作
                for (HttpFlowNodeRecordsQueryVo mapDataVo : mapDataList) {

                    // 任务ID
                    String taskId = mapDataVo.getTaskId();

                    // 任务状态
                    String taskStatus = mapDataVo.getTaskStatus();

                    // 任务处理状态
                    String taskLinkStatus = mapDataVo.getTaskLinkStatus();

                    // 不为空时,校验任务状态
                    if(StringUtils.isNotEmpty(taskId)){
                        // 审批状态
                        String approvalStatus =  this.getApprovalStatus(taskId);

                        // 是否是驳回,如果是驳回,则将其节点添加到集合中
                        if(approvalStatus.equalsIgnoreCase("reject")) {
                            flowNodeRecordsDTO.setProcessInstanceId(mapDataVo.getProcessInstanceId());
                            flowNodeRecordsDTO.setTaskId(mapDataVo.getTaskId());
                            flowNodeRecordsDTO.setNodeCode(mapDataVo.getNodeCode());
                        } else {
                            // 检查任务状态是否是正常且处理状态是否是待处理
                            if(Objects.equals(taskStatus,ProcessInstanceStatusEnum.NORMAL.getCode()) &&
                                    Objects.equals(taskLinkStatus,TaskLinkStatusEnum.TODO.getCode())) {
                                flowNodeRecordsDTO.setProcessInstanceId(mapDataVo.getProcessInstanceId());
                                flowNodeRecordsDTO.setCurrentTaskId(mapDataVo.getTaskId());
                                flowNodeRecordsDTO.setCurrentNodeCode(mapDataVo.getNodeCode());
                            }
                        }
                    }
                    // 走完一次自增一次
                    ++ctn;
                    // 判断是否是最后一次遍历
                    if(ctn == mapDataList.size()) {
                        if(StringUtils.isNotEmpty(flowNodeRecordsDTO.getNodeCode()) &&
                                StringUtils.isNotEmpty(flowNodeRecordsDTO.getCurrentNodeCode())) {
                            filterQueryDtoList.add(flowNodeRecordsDTO);
                            break;
                        }
                    }
                }
            }
        }
        return filterQueryDtoList;
    }

    //增加局部变量返回
    private List<FlowRecordVo> reVarFromResult(List<FlowRecordVo> result){
        //不需要的变量
        List<String> filterVars = Arrays.asList("_processInstanceId","_applyUserId","_modelName","assigned_apply_initiator","_processDefinitionId","_applyUserName"
                ,"_appName","_deploymentId","_modelKey","_appCode","_applyTimeStamp");
        if(CollectionUtils.isNotEmpty(result)){
            for(FlowRecordVo rv : result){
                //过滤开始节点
                if(Objects.equals("start" , rv.getTaskNodeType()) || Objects.equals(TaskLinkStatusEnum.TRANSFER.getCode() , rv.getApprovalStatus())){
                    continue;
                }
                List<HistoricVariableInstance>  hvs = historyService.createHistoricVariableInstanceQuery().taskId(rv.getTaskId()).list();
                if(CollectionUtils.isNotEmpty(hvs)){
                    Map<String, Object> lv = new HashMap<>();
                    for( HistoricVariableInstance hv : hvs){
                        if(filterVars.contains(hv.getVariableName())){
                            continue;
                        }
                        lv.put(hv.getVariableName() , hv.getValue());
                    }
                    rv.setVariablesLocal(lv);
                }
                //递归调用
                reVarFromResult(rv.getChildren());
            }
        }
        return result;
    }

    private  String  getApprovalStatus(String taskId){
        List<HistoricVariableInstance>  historicVariableInstances = historyService.createHistoricVariableInstanceQuery().taskId(taskId).list();
        for(HistoricVariableInstance historicVariableInstance : historicVariableInstances){
            String name = historicVariableInstance.getVariableName();
            if(name.equals("approval")){
                String value = historicVariableInstance.getValue()+"";
                return  value;
            }
        }
        return  ApproveStatus.PROCESSING.getCode();
    }

    public void resolveFlowRecordComment(List<FlowRecordVo> flowRecordVos,List<Comment> comments){

        if(Objects.isNull(comments)){
            return;
        }
        flowRecordVos.stream().forEach(flowRecordVo -> {
            if(StringUtils.isNotEmpty(flowRecordVo.getComment()) && flowRecordVo.getApprovalStatus().equals(TaskLinkStatusEnum.TRANSFER.getCode())){
                return;
            }
            List<Comment> taskComments=new ArrayList<>();
            if (StringUtils.isNotBlank(flowRecordVo.getTaskId())){
                taskComments = comments.stream().filter(comment ->
                        flowRecordVo.getTaskId().equals(comment.getTaskId()) && !comment.getType().equals(CommentTypeEnum.ZB.getName())
                ).collect(Collectors.toList());
            }
            if (flowRecordVo.getTaskNodeType().equals(START_NODE_TYPE)){
                taskComments = comments.stream().filter(comment ->
                        comment.getType().equals(CommentTypeEnum.TJ.getName())
                ).collect(Collectors.toList());
            }
            if (Objects.nonNull(taskComments)){

                taskComments.sort(new Comparator<Comment>() {
                    @Override
                    public int compare(Comment o1, Comment o2) {
                        return o1.getTime().compareTo(o2.getTime());
                    }
                });
                StringBuffer sbf = new StringBuffer();
                for (int i=0;i<taskComments.size();i++) {
                    sbf.append(taskComments.get(i).getFullMessage());
                    if(i < taskComments.size()-1){
                        sbf.append(System.lineSeparator());
                    }
                }
                flowRecordVo.setComment(sbf.toString());
            }
            List<FlowRecordVo> childrens = flowRecordVo.getChildren();
            if (Objects.nonNull(childrens) && childrens.size() > 0){
                resolveFlowRecordComment(childrens,comments);
            }


        });
    }

    @Override
    public TaskFormDetailVo showForm(String taskId) {

        TaskFormDetailVo result = new TaskFormDetailVo();

        if (StringUtils.isBlank(taskId)) {
            return result;
        }

        FlowTaskTraceVo taskTrace = taskTraceService.getTaskTraceByTaskId(taskId);

        if (Objects.isNull(taskTrace)) {
            logger.warn("{} 任务信息不存在", taskId);
            return result;
        }

        if (StringUtils.isBlank(taskTrace.getFormKey())) {
            logger.warn("暂无表单信息");
            return result;
        }

        result = doResolveFormInfo(taskId, isCompleted(taskTrace));

        return result;
    }
    private boolean isCompleted(FlowTaskTraceVo taskTrace) {
        return Objects.nonNull(taskTrace.getCompleteTime()) || Objects.equals(TaskLinkStatusEnum.DONE.getCode(), taskTrace.getLinkStatus());
    }

    @Override
    public List<TaskNoticeVo> listNotices(String taskId) {
        List<FlowRuTimeoutSettingVo> settings = resolveRuSettings(taskId);
        if (CollectionUtils.isEmpty(settings)) {
            return Collections.emptyList();
        }
        List<Long> settingIds = settings.stream().map(FlowRuTimeoutSettingVo::getId).collect(Collectors.toList());
        List<FlowRuTaskNoticeChannelVo> channelSettings = resolveRuChannelSettings(settingIds, taskId);
        Map<Long, List<FlowRuTaskNoticeChannelVo>> settingIdToChannels = channelSettings.stream().collect(Collectors.groupingBy(FlowRuTaskNoticeChannelVo::getRuTimeoutSettingId));
        return resolveTaskNotices(settings, settingIdToChannels);
    }

    @Override
    public TaskLogVo showTaskProcessItem(String taskId) {
        FlowTaskTraceVo taskTrace = taskTraceService.getTaskTraceByTaskId(taskId);
        if (Objects.isNull(taskTrace)) {
            logger.warn("任务跟踪表中不存在记录{}", taskId);
            return null;
        }
        TaskLogVo result = new TaskLogVo(taskTrace);
        result.getCandidateUsers().add(taskTrace.getOperator());
        resolveProcessLimitDuration(result);
        resolveAssigneeItem(result, taskTrace);
        resolveLogs(result, taskId);
        return result;
    }

    @Override
    public PageInfo<RuleActionAuditVo> listRuleActionAudit(RuleActionAuditQueryVo vo) {
        return flowRuleActionAuditLogRepository.listRuleActionAudit(vo);
    }

    private void resolveProcessLimitDuration(TaskLogVo result) {
        List<FlowRuTimeoutSettingVo> ruTimeoutSettings = resolveRuSettings(result.getTaskId());
        if (CollectionUtils.isNotEmpty(ruTimeoutSettings)) {
            Optional<FlowRuTimeoutSettingVo> first = ruTimeoutSettings.stream().filter(item -> Objects.equals(item.getType(), NoticeTypeEnum.TASK_TIMEOUT_NOTICE.getCode())).findFirst();
            if (first.isPresent()) {
                FlowRuTimeoutSettingVo setting = first.get();
                if (Objects.nonNull(setting.getDuration()) && setting.getDuration() > 0) {
                    int day = (int) (setting.getDuration() / (24 * 3600));
                    int hour = (int) ((setting.getDuration() - day * 24 * 3600) / 3600);
                    int minutes = (int) ((setting.getDuration() - day * 24 * 3600 - hour * 3600) / 60);
                    result.setProcessLimitDuration(day + "天" + hour + "小时" + minutes + "分");
                }
            }
        }
    }

    private void resolveLogs(TaskLogVo result, String taskId) {
        List<FlowCommonOperateLogVo> flowCommonOperateLogs = flowCommonOperateLogRepository.listOperateLogs(taskId);
        flowCommonOperateLogs.forEach(item -> item.setType(CommonOperateLogEnum.getDescription(item.getType())));
        result.getLogs().addAll(flowCommonOperateLogs);
    }

    private void resolveAssigneeItem(TaskLogVo result, FlowTaskTraceVo taskTrace) {
        TaskLogVo.AssigneeItem item = new TaskLogVo.AssigneeItem();
        item.setAssignee(taskTrace.getOperator());
        item.setStatus(taskTrace.getStatus());
        item.setLinkStatus(taskTrace.getLinkStatus());
        item.setCategory(taskTrace.getCategory());
        item.setCompleteTime(taskTrace.getCompleteTime());
        if (TaskCategoryEnum.AUDIT.getCode().equals(taskTrace.getCategory())) {
            item.setApproval(resolveAuditResult(taskTrace));
        }
        result.getAssigneeItems().add(item);
    }

    private List<TaskNoticeVo> resolveTaskNotices(List<FlowRuTimeoutSettingVo> settings, Map<Long, List<FlowRuTaskNoticeChannelVo>> settingIdToChannels) {
        List<TaskNoticeVo> result = new LinkedList<>();
        for (FlowRuTimeoutSettingVo setting : settings) {
            boolean isAlreadyNotice = false;
            TaskNoticeVo tmp = new TaskNoticeVo(setting);
            tmp.setNoticeItems(new ArrayList<>());
            List<FlowRuTaskNoticeChannelVo> flowRuTaskNoticeChannels = settingIdToChannels.get(setting.getId());
            tmp.setNoticeItems(new ArrayList<>(flowRuTaskNoticeChannels.size()));
            for (FlowRuTaskNoticeChannelVo channel : flowRuTaskNoticeChannels) {
                if (StringUtils.isNotBlank(channel.getNoticeStatus())) {
                    isAlreadyNotice = true;
                }
                TaskNoticeVo.NoticeItemVo noticeItem = new TaskNoticeVo.NoticeItemVo();
                noticeItem.setRuNoticeChannelId(channel.getId());
                noticeItem.setChannel(NoticeChannelEnum.getDescrByCode(channel.getChannel()));
                noticeItem.setUpdateTime(channel.getUpdateTime());
                noticeItem.setNoticeStatus(channel.getNoticeStatus());
                //todo 设置通讯录地址
                noticeItem.setAddress(channel.getStaCode());

                //todo 设置通知人
                noticeItem.setReceiver(resolveReceiver(channel.getStaCode()));
                tmp.getNoticeItems().add(noticeItem);
            }
            if (isAlreadyNotice) {
                result.add(tmp);
            }
        }
        return result;
    }

    private String resolveReceiver(String staCode) {
        FlowParticipantInfoVo participant = flowParticipantRepository.findByParticipantId(staCode);
        return Objects.nonNull(participant) ? participant.getParticipantName() : null;
    }

    private List<FlowRuTaskNoticeChannelVo> resolveRuChannelSettings(List<Long> settingIds, String taskId) {

        return flowRuTaskNoticeChannelRepository.listFlowRuTaskNoticeChannel(settingIds, taskId);
    }

    private List<FlowRuTimeoutSettingVo> resolveRuSettings(String taskId) {
        return flowRuTimeoutSettingRepository.listFlowRuTimeoutSetting(taskId);
    }

    private TaskFormDetailVo doResolveFormInfo(String taskId, boolean completed) {
        return formRepository.findTaskFormDetail(taskId, completed);
        //FormInfo formInfo = taskService.getTaskFormModel(taskId);
        //SimpleFormModel simpleFormModel = (SimpleFormModel) formInfo.getFormModel();
        //BeanUtils.copyProperties(simpleFormModel, result);
        //result.setFields(FormUtils.getInstance().transformToViewForm(simpleFormModel.getFields()));
        //如果没有提交外部数据，则直接直接调用外部配置获取数据
        //if (completed) {
        //    result.setFields(dataSourceService.processDataSourceConfigAfterSubmit(result.getFields(), null, taskId));
        //} else {
        //    result.setFields(dataSourceService.processDataSourceConfig(result.getFields()));
        //    result.setFields(resetFieldValue(result.getFields()));
        //}
    }

    /*private List<Object> resetFieldValue(List<Object> fields) {
        List<Object> result = new ArrayList<>(fields.size());
        for (Object field : fields) {
            JSONObject formObject = JSON.parseObject(JsonUtils.toJson(field));
            formObject.put("value", "");
            result.add(formObject.toJavaObject(Object.class));
        }
        return result;
    }*/

    private void convertHistoricTaskAndRunningTaskToResult(List<FlowTaskTraceVo> taskTraces, List<FlowRecordVo> result, Map<String, Object> nodeAuth) {
        if (CollectionUtils.isEmpty(taskTraces)) {
            return;
        }

        Set<String> handledRecordIds = new HashSet<>();

        long completedStartTime = System.currentTimeMillis();
        doConvert(taskTraces, result, handledRecordIds, nodeAuth);
        logger.info("convertTask timeCost={}",System.currentTimeMillis()-completedStartTime);

        /*List<FlowTaskTraceVo> completedTaskTraces = taskTraces.stream().filter(item -> Objects.nonNull(item.getCompleteTime())).sorted(Comparator.comparing(FlowTaskTraceVo::getCompleteTime)).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(completedTaskTraces)) {
            long completedStartTime = System.currentTimeMillis();
            doConvert(taskTraces, completedTaskTraces, result, true, handledRecordIds, nodeAuth);
            logger.info("convertCompletedTask timeCost={}",System.currentTimeMillis()-completedStartTime);
        }

        List<FlowTaskTraceVo> runningTaskTraces = taskTraces.stream().filter(item -> Objects.isNull(item.getCompleteTime())).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(runningTaskTraces)) {
            long runningStartTime = System.currentTimeMillis();
            doConvert(taskTraces, runningTaskTraces, result, false, handledRecordIds, nodeAuth);
            logger.info("convertRunningTask timeCost={}",System.currentTimeMillis()-runningStartTime);
        }*/

    }

    private void doConvert(List<FlowTaskTraceVo> sources,  List<FlowRecordVo> result,  Set<String> handledRecordIds
            , Map<String, Object> nodeAuth) {
        User currentUser = resolveCurrentUser();
        for (FlowTaskTraceVo taskTrace : sources) {
            if (handledRecordIds.contains(taskTrace.getId())) {
                //如果该节点已经处理，则不再处理
                continue;
            }
            if (nodeAuth.get(taskTrace.getActivityId()) != null) {
                taskTrace.setNodeAuth(nodeAuth.get(taskTrace.getActivityId()));
            }
            FlowRecordVo item = new FlowRecordVo(taskTrace);
            String operatorName = taskTrace.getOperator();
            boolean isCompleted = Objects.equals(TaskLinkStatusEnum.DONE.getCode(),taskTrace.getLinkStatus());
            // 已处理的任务,则需要查询下员工工号
            if(isCompleted) {
                UserInfo userInfo = null;
                long qryEmployCodeStartTime = System.currentTimeMillis();
                try {
                    userInfo = userService.getUserInfoObj(taskTrace.getOperatorCode());
                } catch (Exception ex) {
                    logger.error("查询用户组件异常,原因为：{}", ex.getMessage(), ex);
                }
                logger.info("qryEmployCode timeCost={}",System.currentTimeMillis()-qryEmployCodeStartTime);
                item.setEmployeeCode(userInfo == null?"":userInfo.getEmployeeCode());
            }
            if(StringUtils.isNotEmpty(operatorName)){
                item.setOperatorName(operatorName);
            }else{
                long getOperatorNameStartTime = System.currentTimeMillis();
                item.setOperatorName(this.getOperatorName(taskTrace.getTaskId()));
                logger.info("qryOperatorName timeCost={}",System.currentTimeMillis()-getOperatorNameStartTime);

            }
            item.setOperatorCode(taskTrace.getOperatorCode());
            Map<String, Object> map = (Map) nodeAuth.get(taskTrace.getActivityId());
            //详情中不显示签收按钮
            //签收按钮的显示逻辑，若当前登录人是候选人，则为true
            if(null!=map) {
                map.put("signIn", false);
            }
            //            //屏蔽会签任务的加签
            //            if (Objects.nonNull(taskTrace.getParentId())){
            //                map.put("addSignature",false);
            //            }
            taskTrace.setNodeAuth(map);
            if (StringUtils.isNotBlank(taskTrace.getOperatorCode()) && Objects.nonNull(currentUser)) {
                if (taskTrace.getOperatorCode().equals(currentUser.getUserCode())) {
                    item.setNodeAuthShow(true);
                }
            }
            if (!item.getNodeAuthShow() && !isCompleted) {
                //如果不是办理人，则判断是否是候选人
                long checkIsCandidateUserStart = System.currentTimeMillis();
                boolean isCandidateUser = isCandidate(taskTrace);
                logger.info("checkIsCandidateUser timeCost={}",System.currentTimeMillis()-checkIsCandidateUserStart);
                if (isCandidateUser){
                    map.put("signIn", true);
                    item.setNodeAuthShow(true);
                }
            }
            if (isMultiInstance(taskTrace)) {
                resolveMultiInstanceTask(sources, item, taskTrace, handledRecordIds,nodeAuth);
            } else {
                if (isAuditCompletedTask(isCompleted, taskTrace)) {
                    //已经完成的审批节点
                    item.setApproval(resolveAuditResult(taskTrace));
                }
                this.getTransferRecords(taskTrace, item, item, map);
            }
            handledRecordIds.add(taskTrace.getId());
            result.add(item);
        }
    }

    private void getTransferRecords(FlowTaskTraceVo taskTrace, FlowRecordVo vo, FlowRecordVo item,Map<String, Object> map) {
        if(map != null && (Boolean) map.get(TaskLinkStatusEnum.TRANSFER.getCode().toLowerCase())){
            Map<String, Comment> commentMap = taskService.getProcessInstanceComments(vo.getProcessInstanceId())
                    .stream()
                    .filter(comment -> comment.getTaskId().equals(vo.getTaskId()))
                    .filter(comment -> comment.getType().equals(CommentTypeEnum.ZB.getName()))
                    .collect(Collectors.toMap(Comment::getId, comment -> comment));
            List<FlowRecordVo> children = item.getChildren();
            List<String> operatorNameList = item.getOperatorNameList();
            flowProcessInstanceOperateTraceRepository.queryFlowProcessInstanceOperateTraceList(vo.getTaskId()).forEach(traceVoOperator -> {
                FlowRecordVo flowRecordVo = new FlowRecordVo();
                BeanUtils.copyProperties(taskTrace, flowRecordVo);
                flowRecordVo.setOperator(traceVoOperator.getOperator());
                flowRecordVo.setOperatorName(traceVoOperator.getOperator());
                flowRecordVo.setOperatorCode(traceVoOperator.getOperatorId());
                flowRecordVo.setCompleteTime(traceVoOperator.getCreateTime());
                if(traceVoOperator.getMessage().equals(TaskLinkStatusEnum.TRANSFER.getDesc())){
                    flowRecordVo.setComment(traceVoOperator.getMessage());
                } else {
                    Optional.ofNullable(commentMap.get(traceVoOperator.getMessage()))
                            .ifPresent(comment -> flowRecordVo.setComment(comment.getFullMessage()));
                }
                flowRecordVo.setLinkStatus(TaskLinkStatusEnum.DONE.getCode());
                flowRecordVo.setApprovalStatus(TaskLinkStatusEnum.TRANSFER.getCode());
                flowRecordVo.setApproval(TaskLinkStatusEnum.TRANSFER.getDesc());
                children.add(flowRecordVo);
                operatorNameList.add(traceVoOperator.getOperator());
            });
            if(children.size() > 0 && !item.getMultiInstance()){
                FlowRecordVo flowRecordVo = new FlowRecordVo();
                BeanUtils.copyProperties(taskTrace, flowRecordVo);
                flowRecordVo.setOperatorName(flowRecordVo.getOperator());
                children.add(flowRecordVo);
            }
            item.setChildren(children);
            item.setOperators(operatorNameList);
            item.setOperatorNameList(operatorNameList);
        }
    }

    private boolean isCandidate(FlowTaskTraceVo taskTrace) {
        if(SessionUtils.getSsoUser() == null){
            return false;
        }

        String userCode = null;
        // 获取当前用户信息
        User user = userRepository.getCurrentUser();
        if (Objects.nonNull(user)){
            userCode = user.getUserCode();
        }
        // 查询返回任务集合
        FlowTaskTraceVo flowTaskTraceVo = flowTaskService.getFlowTaskByTaskIdOrUserCode(taskTrace.getTaskId(),userCode);
        return Objects.nonNull(flowTaskTraceVo);
    }

    private User resolveCurrentUser() {
        if (!SdkCallTag.getTag()) {
            return userRepository.getCurrentUser();
        }
        return null;
    }

    private void resolveMultiInstanceTask(List<FlowTaskTraceVo> sources, FlowRecordVo item, FlowTaskTraceVo taskTrace, Set<String> handledRecordIds,Map<String, Object> nodeAuth) {
        item.setMultiInstance(true);
        User currentUser = resolveCurrentUser();
        if (StringUtils.isNotBlank(taskTrace.getParentId())) {
            //
            List<FlowTaskTraceVo> sameParentIdTasks = sources.stream().filter(it -> (Objects.equals(it.getParentId(), taskTrace.getParentId())
                            && Objects.equals(it.getActivityId(),taskTrace.getActivityId())))
                    .collect(Collectors.toList());
            item.setOperatorNameList(sameParentIdTasks.stream().map(FlowTaskTraceVo::getOperator).collect(Collectors.toList()));
            item.setOperators(sameParentIdTasks.stream().map(FlowTaskTraceVo::getOperator).collect(Collectors.toList()));
            FlowMultiInstanceTaskTraceVo multiRootTaskTrace = flowMultiInstanceTaskTraceRepository.getByRootExecutionId(taskTrace.getParentId());
            if (Objects.nonNull(multiRootTaskTrace)) {
                item.setNumOfHandler(multiRootTaskTrace.getNumOfHandler());
                item.setNumOfInstances(multiRootTaskTrace.getNumOfInstances());
                item.setNumOfCompleted(multiRootTaskTrace.getNumOfPassInstances() + multiRootTaskTrace.getNumOfUnpassInstances());
                item.setStatus(taskTrace.getStatus());
                item.setLinkStatus(multiRootTaskTrace.getLinkStatus());
                if (item.getNumOfCompleted().equals(item.getNumOfHandler())) {
                    //已完成，设置整体的审批意见
                    String approvalResult = "pass";
                    if (multiRootTaskTrace.getNumOfPassInstances() < multiRootTaskTrace.getNumOfUnpassInstances()) {
                        approvalResult = "unpass";
                    }
                    item.setApproval(auditCodeToDescMap.get(approvalResult));

                }

                //设置会签子节点

                for (FlowTaskTraceVo ftt : sameParentIdTasks) {
                    FlowRecordVo child = new FlowRecordVo(ftt);
                    child.setOperatorName(ftt.getOperator());
                    child.setOperatorCode(ftt.getOperatorCode());
                    // 修复Bug<42364>当前任务未完成，不应显示完成时间
                    /*if (Objects.isNull(child.getCompleteTime())) {
                        child.setCompleteTime(ftt.getCreateTime());
                    } else {
                        child.setApproval(resolveAuditResult(ftt));
                    }*/
                    if (!Objects.isNull(child.getCompleteTime())) {
                        child.setApproval(resolveAuditResult(ftt));
                    }
                    Map<String, Object> map = (Map) nodeAuth.get(ftt.getActivityId());
                    child.setNodeAuth(map);
                    if (Objects.nonNull(currentUser) && currentUser.getUserCode().equals(ftt.getOperatorCode())) {
                        child.setNodeAuthShow(true);
                        //如果有一个会签节点的按钮要显示，则父节点的按钮也要显示
                        //审批历史现在的逻辑有问题，会签节点的父任务，是随机的一个子任务编号，导致父任务的nodeAuthShow会判断出错
                        item.setNodeAuthShow(true);
                    }
                    // 已处理的任务,则需要查询下员工工号
                    if(Objects.equals(TaskLinkStatusEnum.DONE.getCode(),ftt.getLinkStatus())) {
                        UserInfo userInfo = null;
                        try {
                            userInfo = userService.getUserInfoObj(ftt.getOperatorCode());
                        } catch (Exception ex) {
                            logger.error("查询用户组件异常,原因为：{}", ex.getMessage(), ex);
                        }
                        child.setEmployeeCode(userInfo == null?"":userInfo.getEmployeeCode());
                    }
                    this.getTransferRecords(ftt, child, item, map);

                    item.getChildren().add(child);
                }

                handledRecordIds.addAll(sameParentIdTasks.stream().map(FlowTaskTraceVo::getId).collect(Collectors.toList()));
            }
        }
    }

    private boolean isMultiInstance(FlowTaskTraceVo taskTrace) {
        return FlowUtils.getInstance().isMultiTaskActivity(taskTrace.getProcessInstanceId(), taskTrace.getActivityId());
    }

    private boolean isAuditCompletedTask(boolean isCompleted, FlowTaskTraceVo taskTrace) {
        return isCompleted && Objects.equals(taskTrace.getCategory(), TaskCategoryEnum.AUDIT.getCode());
    }

    private String resolveAuditResult(FlowTaskTraceVo taskTrace) {
        HistoricVariableInstance approval = historyService.createHistoricVariableInstanceQuery().taskId(taskTrace.getTaskId()).variableName("approval").singleResult();
        return Objects.nonNull(approval) ? auditCodeToDescMap.get(approval.getValue().toString()) : "";
    }


    private void resolveStartNode(String processInstanceId, List<FlowRecordVo> result) {
        FlowProcessInstanceTraceVo psTrace = processInstanceTraceService.getProcessInstanceTraceByProcessInstanceId(processInstanceId);
        if (Objects.isNull(psTrace)) {
            return;
        }

        UserInfo userInfo = null;
        try {
            userInfo = userService.getUserInfoObj(psTrace.getStarterId());
        } catch (Exception ex) {
            logger.error("查询用户组件异常,原因为：{}", ex.getMessage(), ex);
        }
        FlowRecordVo startItem = new FlowRecordVo();
        startItem.setOperatorName(psTrace.getStarterName());
        startItem.setEmployeeCode(userInfo == null?"":userInfo.getEmployeeCode());
        startItem.setCompleteTime(psTrace.getStartTime());
        startItem.setProcessInstanceId(psTrace.getProcessInstanceId());
        startItem.setTaskName("发起流程");
        startItem.setTaskNodeType("start");
        startItem.setCreateTime(psTrace.getCreateTime());
        result.add(startItem);
    }

    @Override
    public List<TaskFormDetailVo> showFormsByInstanceId(String processInstanceId, String branchCode) {
        List<FlowRecordVo> flowRecords = listFlowRecords(processInstanceId);
        List<TaskFormDetailVo> result = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(flowRecords)) {
            for (FlowRecordVo flowRecord : flowRecords) {
                String taskId = flowRecord.getTaskId();
                //过滤掉开始节点和不前缀不匹配的节点，还要过滤掉运行中任务
                if (!match(flowRecord, branchCode)) {
                    continue;
                }
                TaskFormDetailVo taskDetail = showForm(taskId);
                if (Objects.isNull(taskDetail)) {
                    continue;
                }
                result.add(taskDetail);
            }
        }
        return result;
    }

    private boolean match(FlowRecordVo flowRecord, String branchCode) {
        return StringUtils.isNotEmpty(flowRecord.getTaskId())
                && (StringUtils.isEmpty(branchCode)
                || (StringUtils.isNotEmpty(branchCode)
                && flowRecord.getActivityId().startsWith(branchCode)))
                //必须是已经处理完的任务
                && Objects.equals(flowRecord.getLinkStatus(), TaskLinkStatusEnum.DONE.getCode());
    }

    public  String  getOperatorName(String taskId){

        FlowTaskTraceVo flowTaskTraceVo = flowTaskTraceRepository.getTaskTraceByTaskId(taskId);
        CandidateEntity candidateEntity = null;
        Set<String> operatorNameSet = new HashSet<>();

        //如果已完成，则取ACT_HI_TASK中的assignee
        if (Objects.equals(flowTaskTraceVo.getLinkStatus(),TaskLinkStatusEnum.DONE.getCode())){
            HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery().taskId(flowTaskTraceVo.getTaskId()).singleResult();
            StringBuilder builder = new StringBuilder();

            if (Objects.nonNull(historicTaskInstance)){
                String assignee = historicTaskInstance.getAssignee();
                if (StringUtils.isNotBlank(assignee)){
                    candidateEntity = resolveCandidateService.getCandidateEntity("STA",assignee);
                    if (Objects.nonNull(candidateEntity)){
                        builder.append("[").append(CandidateTypeEnum.valueOf("STA").getName()).append("]").append(candidateEntity.getName());
                    }else{
                        logger.error(String.format("根据userCode[%s]获取人员信息失败",assignee));
                    }
                }
            }
            if (StringUtils.isNotBlank(builder)){
                operatorNameSet.add(builder.toString());
            }
        }else{
            try {
                Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
                if (Objects.nonNull(task)){
                    List<IdentityLink> identityLinkList = taskService.getIdentityLinksForTask(taskId);
                    if (Objects.nonNull(identityLinkList) && !identityLinkList.isEmpty()){
                        for (IdentityLink identityLink : identityLinkList) {
                            String candidateType = identityLink.getType();
                            String userId = identityLink.getUserId();
                            String groupId = identityLink.getGroupId();
                            if (Objects.equals("candidate",candidateType)){
                                if (StringUtils.isNotBlank(userId)){
                                    candidateEntity = resolveCandidateService.getCandidateEntity("STA",userId);
                                }else if (StringUtils.isNotBlank(groupId)){
                                    candidateEntity = resolveCandidateService.getCandidateEntity("ORG",groupId);
                                }
                            }else{
                                if (Objects.equals("STA",candidateType)){
                                    candidateEntity = resolveCandidateService.getCandidateEntity(candidateType,userId);
                                }else{
                                    candidateEntity = resolveCandidateService.getCandidateEntity(candidateType,groupId);
                                }
                            }
                            if (Objects.nonNull(candidateEntity)){
                                StringBuilder sbf = new StringBuilder("[");
                                sbf.append(CandidateTypeEnum.valueOf(candidateEntity.getType()).getName())
                                        .append("]").append(candidateEntity.getName());
                                if(CandidateTypeEnum.STA.getCode().equals(candidateEntity.getType())) {
                                    UserInfo userInfo = userService.getUserInfoObj(candidateEntity.getCode());
                                    if (userInfo != null) {
                                        sbf.append("[").append(userInfo.getEmployeeCode()).append("]");
                                    }
                                }
                                operatorNameSet.add(sbf.toString());
                            }
                        }
                    }
                }
            } catch (Exception e) {
                logger.error(String.format("根据taskId[%s]获取任务信息失败",taskId));
            }
        }
        return String.join(",",operatorNameSet);
    }

    private  void  processFlowRecordList(List<FlowTaskTraceVo> flowTaskTraceVoList){
        for(FlowTaskTraceVo flowTaskTraceVo : flowTaskTraceVoList){
            String taskId = flowTaskTraceVo.getTaskId();
            HistoricTaskInstance task =  SpringUtils.getBean(HistoryService.class).createHistoricTaskInstanceQuery().taskId(taskId).singleResult();
            String activityId = task.getTaskDefinitionKey();
            String procDefId =  task.getProcessDefinitionId();
            Process  process = managementService.executeCommand(new Command<Process>() {
                @Override
                public Process execute(CommandContext commandContext) {
                    return ProcessDefinitionUtil.getProcess(procDefId);
                }
            });
            FlowElement flowElement = process.getFlowElement(activityId);
            int  exclusiveFlag = 0;
            if(flowElement != null){
                UserTask userTask = (UserTask)flowElement;
                List<SequenceFlow> sequenceFlowList =  userTask.getOutgoingFlows();
                if(sequenceFlowList.size() == 1){
                    SequenceFlow sequenceFlow =  sequenceFlowList.get(0);
                    FlowElement element = sequenceFlow.getTargetFlowElement();
                    if(element instanceof ExclusiveGateway){
                        exclusiveFlag = 1;
                    }
                }
            }
            flowTaskTraceVo.setExclusiveFlag(exclusiveFlag);
        }
    }

    /**
     * 查询指定当前在指定节点的流程集合
     *
     * @return 任务节点列表
     */
    @Override
    public List<FlowNodeRecordsDTO> getRunningProcessList(HttpGetTaskDto httpGetTaskDto){
        // 根据流程模型编码查询在途的任务列表
        httpGetTaskDto.setModelKey(httpGetTaskDto.getFlowCode());
        List<HttpFlowNodeRecordsQueryVo> taskInstances = flowTaskTraceRepository.getTaskCodeList(httpGetTaskDto);
        if(CollectionUtils.isEmpty(taskInstances)) {
            return Collections.emptyList();
        }

        // 按照流程实例ID进行分组
        Map<String, List<HttpFlowNodeRecordsQueryVo>> dataMap = new HashMap<>();
        for (HttpFlowNodeRecordsQueryVo queryVo : taskInstances) {
            // 首先根据key取出是否存在对应的value,如果不存在,则新创建一个集合添加进去,否则直接add进去
            List<HttpFlowNodeRecordsQueryVo> dataList = dataMap.get(queryVo.getProcessInstanceId());
            if(CollectionUtils.isEmpty(dataList)) {
                List<HttpFlowNodeRecordsQueryVo> initDataList = new ArrayList<>();
                initDataList.add(queryVo);
                // 流程实例ID最为key
                dataMap.put(queryVo.getProcessInstanceId(), initDataList);
            } else {
                dataList.add(queryVo);
                dataMap.put(queryVo.getProcessInstanceId(), dataList);
            }
        }

        // 按照流程实例ID分组完成之后,再迭代map,并取出每个map的key对应的value进行检查
        if(MapUtils.isEmpty(dataMap)) {
            return Collections.emptyList();
        }

        // 存储状态条件过滤之后的数据集合
        List<FlowNodeRecordsDTO> filterQueryDtoList = new ArrayList<>();

        // Map集合循环遍历
        for (Map.Entry<String, List<HttpFlowNodeRecordsQueryVo>> mapObj : dataMap.entrySet()) {
            // 取出对应的value
            List<HttpFlowNodeRecordsQueryVo> mapDataList = mapObj.getValue();
            if(CollectionUtils.isNotEmpty(mapDataList)) {
                int ctn = 0;
                // 一个key只对应一个对象
                FlowNodeRecordsDTO flowNodeRecordsDTO = new FlowNodeRecordsDTO();
                boolean rejected=false;
                // 检验每个任务是否做了驳回操作
                for (HttpFlowNodeRecordsQueryVo mapDataVo : mapDataList) {

                    // 任务ID
                    String taskId = mapDataVo.getTaskId();

                    // 任务状态
                    String taskStatus = mapDataVo.getTaskStatus();

                    // 任务处理状态
                    String taskLinkStatus = mapDataVo.getTaskLinkStatus();

                    // 不为空时,校验任务状态
                    if(StringUtils.isNotEmpty(taskId)){
                        // 审批状态
                        String approvalStatus =  this.getApprovalStatus(taskId);

                        // 是否是驳回,如果是驳回,则将其节点添加到集合中
                        if(approvalStatus.equalsIgnoreCase("reject")) {
                            rejected=true;
                        }

                        // 检查任务状态是否是正常且处理状态是否是待处理
                        if(Objects.equals(taskStatus,ProcessInstanceStatusEnum.NORMAL.getCode()) &&
                                Objects.equals(taskLinkStatus,TaskLinkStatusEnum.TODO.getCode())) {
                            flowNodeRecordsDTO.setProcessInstanceId(mapDataVo.getProcessInstanceId());
                            flowNodeRecordsDTO.setTaskId(mapDataVo.getTaskId());
                            flowNodeRecordsDTO.setTaskCode(mapDataVo.getNodeCode());
                        }
                    }
                    // 走完一次自增一次
                    ++ctn;
                    // 判断是否是最后一次遍历
                    if(ctn == mapDataList.size()) {
                        if(StringUtils.isNotEmpty(flowNodeRecordsDTO.getTaskCode())){
                            flowNodeRecordsDTO.setRejected(rejected);
                            filterQueryDtoList.add(flowNodeRecordsDTO);
                            break;
                        }
                    }
                }
            }
        }
        return filterQueryDtoList;
    }

    @Override
    public List<VariableResult> queryRunningVariableList(VariableQueryVo variableQueryVo) {
        PageHelper.startPage(variableQueryVo.getPageNum(), variableQueryVo.getPageSize());
        PageInfo<ActRuVariable> pageInfo = new PageInfo<>(flowVariableDAO.findVariableInstances(variableQueryVo));
        return getVariableResults(pageInfo.getPageNum(), pageInfo.getPageSize(), this.convert(pageInfo.getList()), pageInfo.getTotal());
    }

    @Override
    public List<VariableResult> queryHistoricVariableList(VariableQueryVo variableQueryVo) {
        PageHelper.startPage(variableQueryVo.getPageNum(), variableQueryVo.getPageSize());
        PageInfo<ActHiVarinst> pageInfo = new PageInfo<>(flowVariableDAO.findHistoricVariableInstances(variableQueryVo));
        return getVariableResults(pageInfo.getPageNum(), pageInfo.getPageSize(), this.convert(pageInfo.getList()), pageInfo.getTotal());
    }

    @Override
    @Transactional
    public boolean updateRunningVariable(VariableResult variableResult) throws Exception {
        String id = Optional.ofNullable(variableResult).map(VariableResult::getId).orElseThrow(Exception::new);
        Object value = Optional.of(variableResult).map(VariableResult::getValue).orElse("");
        String type = Optional.of(variableResult).map(VariableResult::getType).orElse("string");
        ActRuVariable actRuVariable = flowVariableDAO.findVariableByPrimaryKey(id);
        actRuVariable.setRevision(actRuVariable.getRevision() + 1);
        try {
            switch (type){
                case "string":
                    actRuVariable.setTextValue((String) value);
                    break;
                case "double":
                    actRuVariable.setDoubleValue(Double.valueOf(value.toString()));
                    value = Double.valueOf(value.toString());
                    break;
                case "boolean":
                    if(value.equals("true")){
                        value = true;
                        actRuVariable.setLongValue(1L);
                    }else if(value.equals("false")){
                        value = false;
                        actRuVariable.setLongValue(0L);
                    }
                    break;
                case "integer":
                    actRuVariable.setTextValue((String) value);
                    actRuVariable.setLongValue(Long.valueOf(value.toString()));
                    value = Integer.valueOf(value.toString());
                    break;
                case "serializable":
                    try {
                        value = JSON.parse(String.valueOf(value));
                    } catch (Exception e) {
                        try {
                            Map<String, Object> toMap = this.mapStringToMap(String.valueOf(value).replaceAll("[{]", "").replaceAll("[}]", ""));
                            value = new JSONObject(toMap);
                        } catch (Exception ignored) {
                            try {
                                value = JSON.parseArray((String) value);
                            } catch (Exception ignored1) {
                            }
                        }
                    }
                    actRuVariable.setTextValue(JSON.toJSONString(value));
                    break;
                default:
                    actRuVariable.setTextValue((String) value);
            }
        } catch (Exception e) {
            throw new Exception("请输入变量类型对应的值");
        }
        runtimeService.setVariable(actRuVariable.getExecutionId(), actRuVariable.getName(), value);
        FlowVariableLog flowVariableLog = new FlowVariableLog();
        BeanUtils.copyProperties(actRuVariable, flowVariableLog);
        flowVariableLog.setCreateTime(new Date());
        flowVariableDAO.insertVariableLog(flowVariableLog);

        return true;
    }

    private List<VariableResult> getVariableResults(int pageNum, int pageSize, List<VariableResult> variableResults, long total) {
        Page<VariableResult> result = null;
        try {
            result = new Page<>();
            result.setPageNum(pageNum).setPageSize(pageSize).addAll(variableResults);
            result.setTotal(total);
            return result;
        } finally {
            if (Objects.nonNull(result)) {
                result.close();
            }
        }
    }

    private <T extends ActBaseVariable> List<VariableResult> convert(List<T> actRuVariables){
        return actRuVariables.stream().map(actRuVariable -> {
            VariableResult variableResult = new VariableResult();
            BeanUtils.copyProperties(actRuVariable, variableResult);
            String type = actRuVariable.getType();
            Object value = null;
            switch (type){
                case "integer":
                case "string":
                    value = actRuVariable.getTextValue();
                    break;
                case "long":
                case "boolean":
                    value = actRuVariable.getLongValue();
                    break;
                case "double":
                    value = actRuVariable.getDoubleValue();
                    break;
                case "serializable":
                    try {
                        value = this.byteConvertString(actRuVariable);
                    } catch (Exception ignored) {

                    }
                    break;
                default:
                    // longString, null类型暂取textvalue
                    value = actRuVariable.getTextValue();
            }
            variableResult.setValue(value);
            return variableResult;
        }).collect(Collectors.toList());
    }

    private <T extends ActBaseVariable> Object byteConvertString(T actRuVariable){
        Object variable = null;
        if(actRuVariable instanceof ActHiVarinst){
            variable = historyService.createHistoricVariableInstanceQuery().executionId(actRuVariable.getExecutionId()).variableName(actRuVariable.getName());
        }else {
            variable = runtimeService.getVariable(actRuVariable.getExecutionId(),
                    actRuVariable.getName());
        }
        return variable;
    }

    private Map<String, Object> mapStringToMap(String stringMap){
        Map<String,Object> map = new HashMap<>();
        String[] strings = stringMap.split(",");
        for (String str : strings) {
            String[] s = new String[2];
            if(str.contains("=")){
                s = str.split("=");
            }else if(str.contains(":")) {
                s = str.split(":");
            }
            map.put(s[0].trim(), s[1].trim());
        }
        return map;
    }

}
